#include "face_detect_algo.hpp"
#include <string>

FaceDetectAlgo::FaceDetectAlgo()
{
  std::cout << "create face detector..." << std::endl;
}

void FaceDetectAlgo::initConfig(InterfaceSettings &settings)
{
  this->net_ = cv::dnn::readNetFromTensorflow(settings.Get_weight_file(), settings.Get_config_file());
  this->t_score_ = settings.Get_t_score();
  this->show_fps_ = settings.Get_show_fps();
  this->show_score_ = settings.Get_show_score();
}

void FaceDetectAlgo::infer_frame(cv::Mat &frame)
{
  if (frame.empty())
  {
    std::cout << "Error: Frame is empty in infer_frame()" << std::endl;
    return;
  }
  int64 start = cv::getTickCount();
  cv::Mat blob = cv::dnn::blobFromImage(frame, 1.0, cv::Size(300, 300), cv::Scalar(104, 177, 123), false, false);

  this->net_.setInput(blob);
  cv::Mat probs = this->net_.forward();

  // 1x1xNx7
  cv::Mat detectMat(probs.size[2], probs.size[3], CV_32F, probs.ptr<float>());
  for (int row = 0; row < detectMat.rows; row++)
  {
    float conf = detectMat.at<float>(row, 2);
    if (conf > t_score_)
    {
      float x1 = detectMat.at<float>(row, 3) * frame.cols;
      float y1 = detectMat.at<float>(row, 4) * frame.rows;
      float x2 = detectMat.at<float>(row, 5) * frame.cols;
      float y2 = detectMat.at<float>(row, 6) * frame.rows;
      cv::Rect box(x1, y1, x2 - x1, y2 - y1);
      cv::rectangle(frame, box, cv::Scalar(0, 0, 255), 2, 8);
      if (show_score_)
      {
        putText(frame, cv::format("%.2f", conf), cv::Point(x1, y1 - 10), cv::FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(255, 0, 0), 2, 8);
      }
    }
  }
  if (show_fps_)
  {
    float t = (cv::getTickCount() - start) / static_cast<float>(cv::getTickFrequency());
    putText(frame, cv::format("FPS: %.2f", 1.0 / t), cv::Point(20, 40), cv::FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(255, 0, 0), 2, 8);
  }
}
